/*
    Copyright Nicolas Ronvel 2007
	gulix33xp@yahoo.fr

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

using System;
using System.Collections.Generic;
using System.Drawing;

using SdlDotNet.Graphics;
using SdlDotNet.Input;

namespace BlindShark.Widgets
{
	public class ListBox : IWidget
	{
		public delegate void SelectionChangedEvent();
		public SelectionChangedEvent SelectionChanged;
		
		#region Variables
		// The surface to Draw
		Surface _sfListBox;
		
		// listbox location
		Rectangle _rctListBox;
		int _iMaxHeight;
		Size _szElementsSize;
		
		// Buttons
		Button _btnTop;
		Button _btnDown;
		
		// Items list
		List<IListObject> _lsItems;
		int _iItemSelected;
		int _iItemsByPage;
		int _iFirstItem;
		int _iItemHovered;
		
		int _iStep;
		#endregion
		
		
		public ListBox(int listboxHeight, int elementsHeight)
		{
			// Initializing the list
			_lsItems = new List<IListObject>();
			
			// Initializing the buttons
			// Top Button
			_btnTop = new Button("gfx/buttonsTopList.jpg", true);
			_btnTop.Click += new Button.ClickEvent(ClickTop);
			_btnTop.Enabled = false;
			// Down Button
			_btnDown = new Button("gfx/buttonsDownList.jpg", true);
			_btnDown.Click += new Button.ClickEvent(ClickDown);
			_btnDown.Enabled = false;
			
			// Initializing the size 
			_iMaxHeight = listboxHeight;
			_szElementsSize = new Size(0, elementsHeight);
			
			// Initializing the values
			_iItemSelected = -1;
			_iFirstItem = 0;
			_iItemHovered = -1;
			
			_iStep = 5;
			
		}
		
		#region Accessors
		public int X
		{
			get {return _rctListBox.X;}
			set {_rctListBox.X = value;}
		}
		
		public int Y
		{
			get {return _rctListBox.Y;}
			set {_rctListBox.Y = value;}
		}
		
		public IListObject SelectedItem
		{
			get 
			{
				if (_iItemSelected<0)
					return null;
				else
					return _lsItems[_iItemSelected];
			}
		}
		
		public int Width
		{
			get {return _rctListBox.Width;}
		}
		
		public int Height
		{
			get {return _rctListBox.Height;}
		}
		#endregion
		
		#region IWidget interface members
		public Surface Surface
		{
			get {return _sfListBox;}
		}
		
		public Point Location
		{
			get {return _rctListBox.Location;}
			set {_rctListBox.Location = value;}
		}
		
		public void Init()
		{
			// Initializing the Buttons
			// Top Button
			_btnTop.Init();
			// Down Button
			_btnDown.Init();
			
			// Initializing the values
			_szElementsSize.Width = _btnTop.Width;
			_iItemsByPage = (_iMaxHeight - (_btnTop.Height + _btnDown.Height)) / _szElementsSize.Height;
			
			// Initializing the Surface
			_sfListBox = new Surface(new Size(_btnTop.Width, _btnTop.Height + _btnDown.Height + _szElementsSize.Height*_iItemsByPage));
			_rctListBox.Size = new Size(_sfListBox.Width, _sfListBox.Height);
			
			// Initializing the buttons' location
			_btnDown.Location = new Point(_rctListBox.X, _rctListBox.Bottom - _btnDown.Height);
			_btnTop.Location = new Point(_rctListBox.X,_rctListBox.Y);
			
			// Creation the surface
			RefreshingSurface();
		}
		
		public void CleanUp()
		{
			_btnTop.CleanUp();
			_btnDown.CleanUp();
		}
		
		public void HandleEvents()
		{
			bool needRefresh = false;
			
			// Handling Top Button Events
			bool hovered = _btnTop.Hovered;
			bool clicked = _btnTop.Clicked;
			_btnTop.HandleEvents();
			needRefresh = needRefresh || (hovered!=_btnTop.Hovered) || (clicked!=_btnTop.Clicked) || (_btnTop.Clicked && _btnTop.Enabled);
			// Handling Down Button Events
			hovered = _btnDown.Hovered;
			clicked = _btnDown.Clicked;
			_btnDown.HandleEvents();
			needRefresh = needRefresh || (hovered!=_btnDown.Hovered) || (clicked!=_btnDown.Clicked) || (_btnDown.Clicked && _btnDown.Enabled);
				
			// List Events
			// Checking if the mouse is above the list
			Rectangle listArea = new Rectangle(_rctListBox.X, _rctListBox.Y + _btnTop.Height, 
			                                   _rctListBox.Width, _rctListBox.Height - (_btnTop.Height + _btnDown.Height));
			if (listArea.Contains(Mouse.MousePosition))
			{
				int index = (Mouse.MousePosition.Y - listArea.Y) / _szElementsSize.Height;
				if (index + _iFirstItem < _lsItems.Count)
				{
					if ((_iItemSelected != index + _iFirstItem) && Mouse.IsButtonPressed(MouseButton.PrimaryButton))
					{
						_iItemSelected = index + _iFirstItem;
						needRefresh = true;
						if (SelectionChanged != null)
							SelectionChanged();
					}
					else if (_iItemHovered != index + _iFirstItem)
					{
						_iItemHovered = index + _iFirstItem;
						needRefresh = true;
					}
				}
			} else if (_iItemHovered >=0) {
				_iItemHovered = -1;
				needRefresh = true;
			}
			
			if (needRefresh)
				RefreshingSurface();
		}
		#endregion
	
		#region Buttons Events
		public void ClickTop()
		{
			// Decrementing the index of the first item to display
			_iFirstItem -= _iStep;
			if (_iFirstItem<0)
			{
				_iFirstItem = 0;
				_btnTop.Enabled = false;
			}
			if (_lsItems.Count>_iFirstItem + _iItemsByPage)
				_btnDown.Enabled = true;
			
			RefreshingSurface();
		}
		
		public void ClickDown()
		{
			// Incrementing the index of the first item to display
			_iFirstItem += _iStep;
			if (_iFirstItem + _iItemsByPage >= _lsItems.Count)
			{
				_btnDown.Enabled = false;
			}
			if (_iFirstItem > 0)
				_btnTop.Enabled = true;
			
			RefreshingSurface();
		}
		#endregion
		
		#region Drawing functions
		private void RefreshingSurface()
		{
			// Displaying the Buttons
			_sfListBox.Blit(_btnTop.Surface, new Point(_btnTop.X - _rctListBox.X, _btnTop.Y - _rctListBox.Y));
			_sfListBox.Blit(_btnDown.Surface, new Point(_btnDown.X - _rctListBox.X, _btnDown.Y - _rctListBox.Y));
			
			// Displaying the items
			for(int i=0; i<_iItemsByPage; i++)
			{
				//Checking if there is an item at this index
				if (i+_iFirstItem < _lsItems.Count)
				{
					// The Selected Item
					if ((i + _iFirstItem) == _iItemSelected)
						_sfListBox.Blit(_lsItems[i + _iFirstItem].GetSurfaceSelected(_szElementsSize),
						                new Point(0, _btnTop.Height + i * _szElementsSize.Height));
					// The Hovered Item
					else if ((i + _iFirstItem) == _iItemHovered)
						_sfListBox.Blit(_lsItems[i + _iFirstItem].GetSurfaceHovered(_szElementsSize),
						                new Point(0, _btnTop.Height + i * _szElementsSize.Height));
					// Standard Item
					else
						_sfListBox.Blit(_lsItems[i + _iFirstItem].GetSurface(_szElementsSize),
						                new Point(0, _btnTop.Height + i * _szElementsSize.Height));
				} else {
					_sfListBox.Blit(EmptySurface(), new Point(0, _btnTop.Height + i * _szElementsSize.Height));
				}
			}
		}
		
		private Surface EmptySurface()
		{
			Surface sfTemp = new Surface(_szElementsSize);
			sfTemp.Fill(Color.Black);
//			sfTemp.Fill(new Rectangle(1,1,_szElementsSize.Width-2, _szElementsSize.Height-2), Color.Black);
			return sfTemp;
		}
		#endregion
		
		#region List Functions
		public void AddItem(IListObject item)
		{
			_lsItems.Add(item);
			if (_lsItems.Count>_iItemsByPage)
				_btnDown.Enabled = true;
		}
		
		public void Deselect()
		{
			_iItemSelected = -1;
			RefreshingSurface();
		}
		
		public void RemoveSelected()
		{
			if ((_iItemSelected>=0) && (_iItemSelected<_lsItems.Count))
			{
				_lsItems.RemoveAt(_iItemSelected);
				_iItemSelected = -1;
				RefreshingSurface();
			}
		}
		#endregion
	}
}
